added SSCLI 1.0
[windows-sources.git] / shared source / wpf / src / host / shimimpl / watsonreporting.cxx
blobc473c1a5754664d0c8bffe178c4403b047eaefa8
1 //+-----------------------------------------------------------------------
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // Description:
6 // [see .hxx]
7 //
8 // History:
9 // 2007/07/20 [....] Created
10 // 2007/09/20 [....] Ported Windows->DevDiv. See SourcesHistory.txt.
12 //------------------------------------------------------------------------
14 #include "precompiled.hxx"
15 #include "WatsonReporting.hxx"
16 #include <fxver.h>
18 #ifdef APPLICATION_SHIM
20 // Curiously, XPSViewer seems capable of coping with all the problems detected here. That's because
21 // it doesn't use ClickOnce and also because if IPersistMoniker marshaling fails, IE's fallback to
22 // IPersistFile still works for XPSViewer.
23 // That's why all this code is conditionally compiled only for PH.exe.
25 // HKCU\Software\Classes is persisted in a separate file and on many computers permissons are set
26 // explicitly, not inherited. This must be somehow part of the explanation of how the ACL entry for the
27 // individual user account can be missing.
28 HRESULT CheckRegistryAccess()
30 HKEY hKey;
31 int error = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, KEY_READ, &hKey);
32 if (error == ERROR_SUCCESS)
34 RegCloseKey(hKey);
35 return S_OK;
38 // Dev10 bug 707086 - HKCU\SOFTWARE\Classes may not exist on clean XP installations.
39 // ClickOnce will create it, so don't bother about it here.
40 if (error == ERROR_FILE_NOT_FOUND)
42 return S_OK;
45 HRESULT hr = HRESULT_FROM_WIN32(error);
46 TriggerWatson(ActivationProblemIds::HKCUClassesAccessDenied);
47 return hr;
50 // Only read access to %LocalAppData% is tested here. ClickOnce needs access to %LocalAppData%\Deployment.
51 // Other profile folders may also be susceptible to the ACL anomaly, but unless we get actual reports of
52 // such cases, it doesn't make much sense to generalize the test.
53 // Worth noting is that denied access to the Temporary Internet Files folder does not break PresentationHost
54 // activation.
55 HRESULT CheckAppDataFolderAccess()
57 wchar_t path[MAX_PATH];
58 HRESULT hr = SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, SHGFP_TYPE_CURRENT, path);
59 if(hr == S_OK)
61 StringCchCat(path, ARRAYSIZE(path), L"\\*");
62 WIN32_FIND_DATA findData;
63 HANDLE hFind = FindFirstFile(path, &findData);
64 if(hFind != INVALID_HANDLE_VALUE)
66 FindClose(hFind);
68 else if(GetLastError() == ERROR_ACCESS_DENIED)
70 TriggerWatson(ActivationProblemIds::AppDataFolderAccessDenied);
71 hr = E_ACCESSDENIED;
74 return hr;
77 void TriggerWatson(LPCWSTR problemId)
79 HRESULT hr = S_OK;
81 // Invoke Watson in manifest mode:
82 // http://msdn2.microsoft.com/en-us/library/bb219076.aspx#MicrosoftErrorReporting_AboutManifestMode
83 // We rely on the .NET Framework setup to install dw20.exe.
85 #define CRLF L"\r\n"
87 const wchar_t report[] = CRLF // required blank line
88 L"Version=131072" CRLF
89 L"ReportingFlags=2048" CRLF // fDwrCriticalEvent
90 L"General_AppName=" TEXT(SHIM_COMPONENT_DESCRIPTION) CRLF
91 L"FilesToKeep=null" CRLF
92 L"EventType=" ACTIVATION_PROBLEM_WATSON_EVENT CRLF //***
93 L"P1=" TEXT(TARGETNAME) CRLF
94 L"P2=" TEXT(FX_VER_FILEVERSION_STR) CRLF;
95 //P3=OS version - added below
96 //P4=problemId - added below
98 OSVERSIONINFOEX OSInfo = { sizeof OSInfo };
99 HANDLE hFile = 0;
100 DWORD cBytesWritten;
101 wchar_t DWPath[MAX_PATH];
102 DWORD cch;
103 wchar_t cmdLine[3*MAX_PATH];
104 STARTUPINFO startupInfo = { sizeof STARTUPINFO };
105 PROCESS_INFORMATION processInfo;
106 DWORD exitCode;
108 // Create the report file
109 wchar_t reportFilepath[MAX_PATH] = { 0 };
110 GetTempPath(ARRAYSIZE(reportFilepath), reportFilepath);
111 CHECK_ZERO_FROM_WIN32(GetTempFileName(reportFilepath, L"PH", 0, reportFilepath));
112 hFile = CreateFile(reportFilepath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
113 CHECK_BOOL_FROM_WIN32(hFile && hFile != INVALID_HANDLE_VALUE);
114 CHECK_BOOL_FROM_WIN32(WriteFile(hFile, report, sizeof report - sizeof L'\0', &cBytesWritten, 0));
115 if(GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&OSInfo)))
117 wchar_t strOSVersion[96];
118 SYSTEM_INFO sysInfo;
119 GetNativeSystemInfo(&sysInfo);
120 StringCchPrintf(strOSVersion, ARRAYSIZE(strOSVersion),
121 L"P3=%d.%d.%d.%d.%d%s" CRLF,
122 OSInfo.dwMajorVersion, OSInfo.dwMinorVersion, OSInfo.dwBuildNumber,
123 OSInfo.wServicePackMajor, OSInfo.wServicePackMinor,
124 sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? L" (x64)" : L"");
125 WriteFile(hFile, strOSVersion, (DWORD)wcslen(strOSVersion)*2, &cBytesWritten, 0);
127 if(problemId)
129 WriteFile(hFile, L"P4=", 3*sizeof(wchar_t), &cBytesWritten, 0);
130 WriteFile(hFile, problemId, (DWORD)wcslen(problemId)*sizeof(*problemId), &cBytesWritten, 0);
131 WriteFile(hFile, CRLF, sizeof CRLF - sizeof L'\0', &cBytesWritten, 0);
133 CloseHandle(hFile);
135 // Invoke dw20.exe -d <report filepath>
136 // Using ShellExecute() would be simpler, but it relies heavily on registry keys, and we have an ACL
137 // problem, so ShellExecute() might fail.
139 // Apparently DW is installed only as a 32-bit build.
140 #ifdef _WIN64
141 cch = GetEnvironmentVariable(L"CommonProgramFiles(x86)", DWPath, ARRAYSIZE(DWPath));
142 #else
143 cch = GetEnvironmentVariable(L"CommonProgramFiles", DWPath, ARRAYSIZE(DWPath));
144 #endif
145 CKHR(StringCchCopy(DWPath+cch, ARRAYSIZE(DWPath)-cch, L"\\Microsoft Shared\\DW\\dw20.exe"));
146 // Conventionally, the first command line item is the executable's filepath.
147 CKHR(StringCchPrintf(cmdLine, ARRAYSIZE(cmdLine), L"\"%s\" -d \"%s\"", DWPath, reportFilepath));
148 CHECK_BOOL_FROM_WIN32(CreateProcess(DWPath, cmdLine, 0, 0, 0, 0, 0, 0, &startupInfo, &processInfo));
149 WaitForSingleObject(processInfo.hProcess, INFINITE);
150 CHECK_BOOL_FROM_WIN32(GetExitCodeProcess(processInfo.hProcess, &exitCode));
151 hr = exitCode == 0 ? S_OK : E_FAIL;
153 Cleanup:
154 // No cleanup really needed. Mission failed...
156 // Fallback: just raise an exception
157 if(FAILED(hr))
159 ReportFaultAndTerminate(hr, ACTIVATION_PROBLEM_FALLBACK_EXCEPTION_CODE);
163 #endif // APPLICATION_SHIM